/*******************************************************************************
 * Copyright 2010 Simon Mieth
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/

package org.kabeja.svg.generators;

import java.util.Map;

import org.kabeja.common.DraftEntity;
import org.kabeja.entities.Ellipse;
import org.kabeja.math.Point3D;
import org.kabeja.math.TransformContext;
import org.kabeja.svg.SVGConstants;
import org.kabeja.svg.SVGPathBoundaryGenerator;
import org.kabeja.svg.SVGUtils;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;


public class SVGEllipseGenerator extends AbstractSVGSAXGenerator
    implements SVGPathBoundaryGenerator {
    public void toSAX(ContentHandler handler, Map svgContext, DraftEntity entity,
        TransformContext transformContext) throws SAXException {
        Ellipse ellipse = (Ellipse) entity;

        AttributesImpl attr = new AttributesImpl();
        super.setCommonAttributes(attr, svgContext, ellipse);

        if ((ellipse.getStartParameter() == Ellipse.DEFAULT_START_PARAMETER) &&
                (ellipse.getEndParameter() == Ellipse.DEFAULT_END_PARAMETER)) {
            SVGUtils.addAttribute(attr, "cx",
                SVGUtils.formatNumberAttribute(ellipse.getCenterPoint().getX()));
            SVGUtils.addAttribute(attr, "cy",
                SVGUtils.formatNumberAttribute(ellipse.getCenterPoint().getY()));

            double major = ellipse.getHalfMajorAxisLength();
            double minor = ellipse.getRatio() * major;
            SVGUtils.addAttribute(attr, "rx",
                SVGUtils.formatNumberAttribute(major));
            SVGUtils.addAttribute(attr, "ry",
                SVGUtils.formatNumberAttribute(minor));

            // chek for rotation
            double angle = ellipse.getRotationAngle();

            if (angle != 0.0) {
                StringBuffer buf = new StringBuffer();
                buf.append("rotate(");
                buf.append(SVGUtils.formatNumberAttribute(Math.toDegrees(angle)));
                buf.append(' ');
                buf.append(SVGUtils.formatNumberAttribute(
                        ellipse.getCenterPoint().getX()));
                buf.append(' ');
                buf.append(SVGUtils.formatNumberAttribute(
                        ellipse.getCenterPoint().getY()));
                buf.append(')');
                SVGUtils.addAttribute(attr, "transform", buf.toString());
            }

            // SVGUtils.addAttribute(attr, "fill", "none");
            SVGUtils.emptyElement(handler, SVGConstants.SVG_ELLIPSE, attr);
        } else {
            SVGUtils.addAttribute(attr, "d", getSVGPath(ellipse));
            SVGUtils.emptyElement(handler, SVGConstants.SVG_PATH, attr);
        }
    }

    public String getSVGPath(DraftEntity entity) {
        Ellipse ellipse = (Ellipse) entity;

        StringBuffer buf = new StringBuffer();

        Point3D start = ellipse.getPointAt(ellipse.getStartParameter());
        Point3D end = ellipse.getPointAt(ellipse.getEndParameter());

        buf.append("M ");
        buf.append(SVGUtils.formatNumberAttribute(start.getX()));
        buf.append(' ');
        buf.append(SVGUtils.formatNumberAttribute(start.getY()));

        // get the angle between x-axis and major-axis
        double major = ellipse.getMajorAxisDirection().getLength();
        double angle = ellipse.getRotationAngle();

        buf.append(" A ");
        buf.append(SVGUtils.formatNumberAttribute(major));
        buf.append(' ');
        buf.append(SVGUtils.formatNumberAttribute(major * ellipse.getRatio()));
        buf.append(' ');
        // rotation value of the ellipse
        buf.append(SVGUtils.formatNumberAttribute(Math.toDegrees(angle)));

        if ((ellipse.getStartParameter() == Ellipse.DEFAULT_START_PARAMETER) &&
                (ellipse.getEndParameter() == Ellipse.DEFAULT_END_PARAMETER)) {
            // drawing a full ellipse -> from start point to half
            // and then back

            // the large-arc flag and the sweep-flag always 1
            buf.append(" 1 1 ");

            buf.append(SVGUtils.formatNumberAttribute(end.getX()));
            buf.append(' ');
            buf.append(SVGUtils.formatNumberAttribute(end.getY()));

            buf.append(" A ");
            buf.append(SVGUtils.formatNumberAttribute(major));
            buf.append(' ');
            buf.append(SVGUtils.formatNumberAttribute(
                    major * ellipse.getRatio()));
            buf.append(' ');

            // rotation value of the ellipse
            buf.append(SVGUtils.formatNumberAttribute(Math.toDegrees(angle)));

            buf.append(" 1 1 ");

            buf.append(SVGUtils.formatNumberAttribute(start.getX()));
            buf.append(' ');
            buf.append(SVGUtils.formatNumberAttribute(start.getY()));

            // buf.append(" z ");
        } else {
            //TODO check the correct flags 
            //
            buf.append(' ');

            // the large-arc flag
            if ((ellipse.getEndParameter() - ellipse.getStartParameter()) >= Math.PI) {
                buf.append(1);
            } else {
                buf.append(0);
            }

            buf.append(' ');

            // the sweep-flag always 1
            buf.append(" 1 ");

            buf.append(SVGUtils.formatNumberAttribute(end.getX()));
            buf.append(' ');
            buf.append(SVGUtils.formatNumberAttribute(end.getY()));
        }

        return buf.toString();
    }
}
